<html>

<head>
    <meta charset="UTF-8">
    <!-- 自适配手机端尺寸 -->
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
    <!-- 在 head 标签中添加 meta 标签，并设置 viewport-fit=cover 值 -->
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
    <title>琪想垚茶町</title>

    <!--  -->
    <!-- head标签之间，引入第三方依赖库 -->
    <!--  -->
    <!-- 引入样式文件 -->
    <!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.2/lib/index.css" /> -->
    <link rel="stylesheet" href="lib/npm/vant@2.2/lib/index.css" />
    <!-- 引入 Vue v2.7.16 和 Vant v2.2.16 的 JS 文件 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script> -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vant@2.2/lib/vant.min.js"></script> -->
    <script src="lib/npm/vue/dist/vue.min.js"></script>
    <script src="lib/npm/vant@2.2/lib/vant.min.js"></script>
    <!-- 引入 Axios -->
    <script src="lib/axios/dist/axios.min.js"></script>

    <!-- Vue 路由 4.0.12 -->
    <!--    <script src="https://unpkg.com/vue-router@4"></script>-->
    <script src="./lib/vue-router@4.0.12/dist/vue-router.global.js"></script>

    <!-- 配置文件 -->
    <script src="./config/config.js"></script>

</head>

<body style="background-attachment: fixed;">


    <!--  -->
    <!-- 主代码 1/8 定义vue挂载元素，和APP头部，尾部展示内容。 -->
    <!--  -->
    <div id="app" style="opacity: 0.9;min-height: 100%;background-color: #fff;">

        <!-- 顶部 -->
        <div class="nav">

            <van-nav-bar :title="sharedState.title" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
                <div v-if="sharedState.token" slot="right">{{sharedState.user}} 退出</div>
                <div v-if="!sharedState.token" slot="right">登录</div>
            </van-nav-bar>
            <!-- <a href="#/home" @click.prevent="navigateTo('/home')">首页</a> -->
            <!-- <a href="#/about" @click.prevent="navigateTo('/orderList')">orderList</a> -->
            <!-- <a href="#/contact" @click.prevent="navigateTo('/contact')">联系</a> -->

        </div>
        <div>


            <!--  -->
            <!-- 主代码 2/8 定义vue组件引用，通过路由切换APP主体内容切换不同的组件。 -->
            <!--  -->
            <!-- 中间组件 -->
            <component :is="currentComponent"></component>

        </div>
        <div>

            <!-- 底部 -->
            <van-tabbar v-model="sharedState.activeName">
                <van-tabbar-item v-if="!sharedState.admin" name="home" icon="wap-home-o">首页</van-tabbar-item>
                <van-tabbar-item v-if="!sharedState.admin" name="orderList" icon="search">订单</van-tabbar-item>
                <!-- <van-tabbar-item name="item" icon="manager-o">促销活动</van-tabbar-item> -->
                <van-tabbar-item v-if="!sharedState.admin" name="contact" icon="contact">客服</van-tabbar-item>
                <van-tabbar-item v-if="sharedState.admin" name="orderListManage" icon="manager-o">订单管理</van-tabbar-item>
                <van-tabbar-item v-if="sharedState.admin" name="item" icon="manager-o">商品管理</van-tabbar-item>
                <van-tabbar-item v-if="sharedState.admin" name="contact" icon="contact">用户反馈</van-tabbar-item>
                <!-- <van-tabbar-item v-if="sharedState.admin" name="item" icon="manager-o">活动管理</van-tabbar-item> -->
                <!-- <van-tabbar-item name="item" icon="manager-o">使用取餐码</van-tabbar-item> -->
                <van-tabbar-item name="personList" icon="manager-o">个人中心</van-tabbar-item>
            </van-tabbar>

        </div>
    </div>

    <div id="app-main">

    </div>

    <div id="app-message">

    </div>

</body>

<!-- 路由 -->
<!-- <script src="router/router.js"></script> -->

<script>

    // <!--  -->
    // <!-- 主代码 3/8 定义公共js方法，在整个前端项目中的公用方法。 -->
    // <!-- 包括1.元素滚动到屏幕里并高亮该元素，2.时间格式化等公共方法。 -->
    // <!--  -->
    /**
     * 高亮元素并定位
     * @author 陈晓琪
     * @since 2025年5月17日09:39:44
     */
    function highlightElement(id, highlightColor = '#aaa', duration = 100) {
        const el = document.getElementById(id);
        if (!el) return;

        // 平滑滚动到元素
        el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });

        // 保存原始样式
        const oldColor = el.style.backgroundColor;
        const oldTransition = el.style.transition;

        // 设置过渡效果
        el.style.transition = `background-color ${duration}ms ease-in-out`;
        el.style.backgroundColor = highlightColor;

        // 恢复原始颜色
        setTimeout(() => {
            el.style.backgroundColor = oldColor;

            // 恢复原始过渡设置
            setTimeout(() => {
                el.style.transition = oldTransition;
            }, duration);
        }, 100);
    }

    /**
     * 定位之后再高亮元素
     * 使用 IntersectionObserver（更精确的检测）
     * @author 陈晓琪
     * @since 2025年5月17日09:45:28
     * @see <a href="ai@deepseek">高亮元素并添加渐变动画,在滚动到位后再开始渐变</a>
     */
    function highlightAfterScroll(id, highlightColor = '#aaa', duration = 300) {
        const el = document.getElementById(id);
        if (!el) return;

        const oldColor = el.style.backgroundColor;
        const oldTransition = el.style.transition;

        // 创建观察者
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    // 元素进入视口，停止观察
                    observer.unobserve(el);

                    // 开始颜色变化
                    el.style.transition = `background-color ${duration}ms ease-in-out`;
                    el.style.backgroundColor = highlightColor;

                    // 恢复原始颜色
                    setTimeout(() => {
                        el.style.backgroundColor = oldColor;

                        // 恢复原始过渡设置
                        setTimeout(() => {
                            el.style.transition = oldTransition;
                        }, duration);
                    }, duration);
                }
            });
        }, { threshold: 1.0 }); // 当元素完全可见时触发

        // 开始滚动并观察
        el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        observer.observe(el);
    }

    /**
     * 格式化时间字符串
     * @param {string|Date} timeStr - 时间字符串或Date对象
     * @param {string} [format="yyyy-MM-dd HH:mm:ss"] - 格式化模板
     * @returns {string} 格式化后的时间字符串
     */
    function formatTime(timeStr, format = "yyyy-MM-dd HH:mm:ss") {
        let date;

        // 处理输入参数
        if (timeStr instanceof Date) {
            date = timeStr;
        } else if (typeof timeStr === 'string' || typeof timeStr === 'number') {
            // 尝试解析时间字符串或时间戳
            date = new Date(timeStr);

            // 如果解析失败，尝试处理常见的日期格式
            if (isNaN(date.getTime())) {
                // 处理不带时区的ISO格式（如"2011-10-10 14:48:00"）
                date = new Date(timeStr.replace(/-/g, '/').replace(/T/g, ' '));
            }
        } else {
            throw new Error('Invalid time format');
        }

        // 检查日期是否有效
        if (isNaN(date.getTime())) {
            throw new Error('Invalid date');
        }

        // 提取日期各部分
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const day = date.getDate();
        const hours = date.getHours();
        const minutes = date.getMinutes();
        const seconds = date.getSeconds();
        const milliseconds = date.getMilliseconds();

        // 星期几（0-6，0表示星期日）
        const weekDay = date.getDay();
        const weekDays = ['日', '一', '二', '三', '四', '五', '六'];

        // 补零函数
        const padZero = (num, len = 2) => num.toString().padStart(len, '0');

        // 替换格式化字符串中的占位符
        return format
            .replace(/yyyy/g, year)
            .replace(/yy/g, padZero(year % 100))
            .replace(/MM/g, padZero(month))
            .replace(/M/g, month)
            .replace(/dd/g, padZero(day))
            .replace(/d/g, day)
            .replace(/HH/g, padZero(hours))
            .replace(/H/g, hours)
            .replace(/hh/g, padZero(hours % 12 || 12))
            .replace(/h/g, hours % 12 || 12)
            .replace(/mm/g, padZero(minutes))
            .replace(/m/g, minutes)
            .replace(/ss/g, padZero(seconds))
            .replace(/s/g, seconds)
            .replace(/SSS/g, padZero(milliseconds, 3))
            .replace(/SS/g, padZero(Math.floor(milliseconds / 10)))
            .replace(/S/g, Math.floor(milliseconds / 100))
            .replace(/E/g, weekDays[weekDay])
            .replace(/a/g, hours < 12 ? '上午' : '下午')
            .replace(/A/g, hours < 12 ? 'AM' : 'PM');
    }
</script>
<script>

    // <!--  -->
    // <!-- 主代码 4/8 定义vue统一状态管理。 -->
    // <!--  -->
    /**
     * 共享的状态管理
     * @see <a href="https://v2.cn.vuejs.org/v2/guide/state-management.html"></a>
     */
    var store = {
        debug: true,
        state: {
            message: 'Hello!',
            title: '琪想垚茶町',
            currentRoute: window.location.hash.slice(1) || '/home',
            activeName: 'home',
            // 登录相关
            token: '',
            user: '未登录',
            admin: false,
            componentState: {},
        },
        setMessageAction(newValue) {
            if (this.debug) console.log('setMessageAction triggered with', newValue)
            this.state.message = newValue
        },
        clearMessageAction() {
            if (this.debug) console.log('clearMessageAction triggered')
            this.state.message = ''
        }
    }

    // <!--  -->
    // <!-- 主代码 5/8 定义vue后端接口及对应的接口函数的封装和调用。 -->
    // <!--  -->
    var token = ''
    var urls = {
        reg: serverUrl + '/auth/register',
        login: serverUrl + '/auth/login',
        logout: serverUrl + '/auth/logout',
        updatePass: serverUrl + '/auth/changePass',
        listItem: serverUrl + '/order/listItem',
        createOrder: serverUrl + '/order/createOrder',
        listOrder: serverUrl + '/order/listOrder',
        listOrderManage: serverUrl + '/order/listOrderManage',
        waitingOrder: serverUrl + '/order/waitingOrder',
        codeOrder: serverUrl + '/order/codeOrder',
        payOrder: serverUrl + '/order/payOrder',
        cancelOrder: serverUrl + '/order/cancelOrder',
        findOrder: serverUrl + '/order/findOrder',
        addMsg: serverUrl + '/msg/add',
        updateMsg: serverUrl + '/msg/update',
        deleteMsg: serverUrl + '/msg/delete',
        pageMsg: serverUrl + '/msg/page',
        deleteItem: serverUrl + '/item/delete',
        updateItem: serverUrl + '/item/update',
        addItem: serverUrl + '/item/add',
        fileUpload: serverUrl + '/file/upload',
        updateUser: serverUrl + '/user/update',
        listUser: serverUrl + '/user/list',
    }
    // 前端请求认证拦截器
    var apiInterceptor = (res) => {
        if (res && res.data && res.data.code == 10000) {
            vant.Toast("登录过期")
            delete localStorage['token']
            token = ''
            globalThis.token = ''
            store.state.token = ''
            store.state.user = ''
            store.state.info = {}
            store.state.admin = false
            window.location.hash = '#/login'
            throw new Error("登录过期")
        }
    }
    var api = {
        async reg(param = {}) {
            let res = await axios.post(urls.reg, param)
            return res.data
        },
        async login(param = {}) {
            let res = await axios.post(urls.login, param)
            return res.data
        },
        async logout() {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.logout, {}, { headers })
            return res.data
        },
        async listItem(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.listItem, { headers })
            apiInterceptor(res)
            return res.data
        },
        async createOrder(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.createOrder, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async listOrder(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.listOrder, { headers })
            apiInterceptor(res)
            return res.data
        },
        async orderListManage(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.listOrderManage, { headers })
            apiInterceptor(res)
            return res.data
        },
        async payOrder(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.payOrder + `?orderId=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async cancelOrder(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.cancelOrder + `?orderId=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async waitingOrder(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.waitingOrder + `?orderId=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async codeOrder(id, orderCode) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.codeOrder + `?orderId=${id}&orderCode=${orderCode}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async findOrder(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.findOrder + `?orderId=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async addMsg(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.addMsg, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async updateMsg(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.updateMsg, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async deleteMsg(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.deleteMsg + `?id=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async pageMsg(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.pageMsg, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async deleteItem(id) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.deleteItem + `?id=${id}`, { headers })
            apiInterceptor(res)
            return res.data
        },
        async updateItem(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.updateItem, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async addItem(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.addItem, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async fileUpload(formData = new FormData()) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.fileUpload, formData, { headers })
            apiInterceptor(res)
            return res.data
        },
        async updateUser(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.updateUser, param, { headers })
            apiInterceptor(res)
            return res.data
        },
        async listUser(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.get(urls.listUser, { headers })
            apiInterceptor(res)
            return res.data
        },
        async updatePass(param = {}) {
            let headers = {
                "authorization": token
            }
            let res = await axios.post(urls.updatePass, param, { headers })
            apiInterceptor(res)
            return res.data
        },
    }

    // <!--  -->
    // <!-- 主代码 6/8 定义vue的不同页面的路由组件和组件里的方法。 -->
    // <!-- 包括普通用户：商品列表，订单列表，客服，个人中心 -->
    // <!-- 包括管理员用户：订单管理，商品管理，个人中心 -->
    // <!--  -->
    // 定义路由组件
    const Home = {
        template: `
        <div>
            <van-swipe :autoplay="3000" :height="320">
                <van-swipe-item v-for="(image, index) in images" :key="index">
                    <img style="width:100%;" :src="image" />
                </van-swipe-item>
            </van-swipe>
            <van-row type="flex">
            <div style="height:auto;background-color:#fff;">
                <van-sidebar v-model="activeKey">
                    <van-sidebar-item v-for="(item, index) in list" :title="item.type"  @click="doScroll(item)" />
                </van-sidebar>
            </div>
            <van-list style="width:100%;"
            v-model="loading"
            :finished="finished"
            finished-text="没有更多了"
            error-text="请求失败，点击重新加载"
            @load="onLoad"
            >

                <!--使用title-style title-class label-class value-class 自定义样式，通过设置less-spacing减少标题和标题下方的描述信息的间距 -->
                <van-cell-group>
                    <van-cell
                        v-for="(item, index) in list"
                        :key="index"
                        less-spacing
                        title-style="flex: 3"
                        title-class="van-multi-ellipsis--l2"
                        label-class="font-size0 van-color-text-secondary"
                        value-class="margin-left38 flex-align-spacebetween"
                        :id="item.id"
                    >

                        <template slot="title">
                            <span class="van-multi-ellipsis--l2">{{ item.name }}</span>
                            <img style="width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+item.imageUrl" />

                        </template>
                        <template slot="label">{{ item.type }} </template>
                        <template>

                            <van-space direction="vertical" fill>
                                <div class="font-size1 van-color-text-assist">
                                    库存 {{ item.quantity }}
                                </div>
                                <div class="font-size2 van-color-text-assist">
                                    {{ item.price }}
                                    <i class="font-size-2">元</i>
                                </div>
                                <div>
                                    <van-stepper 
                                            min="0"
                                        slot="right-icon"
                                        v-model="item.stepper"
                                        button-size="13px"
                                        input-width="30px"
                                        button-size="14px"
                                        input-width="30px"
                                        class="absolute right14"
                                        @change="handleChange(item)"
                                    />
                                </div>
                            </van-space>
                        </template>

                    </van-cell>
                </van-cell-group>



                <!-- 输入框 -->
            <van-dialog v-model="show" title="请下单" show-cancel-button :lazy-render="false"
                @confirm="doCreateOrder" 
                @cancel=""    
            >

            <div >
                        <van-cell
                            less-spacing
                            title-style="flex: 5"
                            title-class="van-multi-ellipsis--l2"
                            label-class="font-size0 van-color-text-secondary"
                            value-class="margin-left38 flex-align-spacebetween"
                        >
                        <template>
                            </template>
                            <template slot="title">

                            <van-grid>
                                <div v-for="(it, ind) in remarkItems" @click="()=>{remarkItem=it;remarkItem.clicked=true;}">
                                 
                                <img :key="'b'+it.ind" v-if="remarkItem.ind==it.ind" style="margin-right:2px;border: solid 1px;border-color:#ee0a24;width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+it.imageUrl" />
                                <img :key="'s'+it.ind" v-if="remarkItem.ind!=it.ind&&!it.clicked" style="margin-right:2px;border: solid 1px;border-color:#fff;width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+it.imageUrl" />
                                <img :key="'s'+it.ind" v-if="remarkItem.ind!=it.ind&&it.clicked" style="margin-right:2px;border: solid 1px;border-color:#3f3;width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+it.imageUrl" />
                                    </div>
                            </van-grid>

                            </template>
                            <template slot="label" v-if="orderItemCount<=1">
                                请选择口味
                                </template>
                            <template slot="label" v-if="orderItemCount>1">
                                请选择商品的口味
                                </template>
                            <template>
                            <span class="font-size2 van-color-text-assist">
                            
                                总价<i class="font-size-2"> 11 </i> 元
                            </span>
                            </template>

                        </van-cell>

                        <van-cell>
                            | 温度
                        </van-cell>
                        
                        <van-cell>
                            <van-button size="small"
                             :type="remarkItem.temp=='正常冰'?'danger':''"
                             @click="handleTemp(remarkItem,'正常冰')"
                            >正常冰</van-button>
                            <van-button size="small"
                             :type="remarkItem.temp=='少冰'?'danger':''"
                             @click="handleTemp(remarkItem,'少冰')"
                            >少冰</van-button>
                            <van-button size="small"
                             :type="remarkItem.temp=='常温'?'danger':''"
                             @click="handleTemp(remarkItem,'常温')"
                            >常温</van-button>
                            <van-button size="small"
                             :type="remarkItem.temp=='热'?'danger':''"
                             @click="handleTemp(remarkItem,'热')"
                            >热</van-button>
                        </van-cell>
                        <van-cell>
                            | 糖度
                        </van-cell>
                        
                        <van-cell>
                            <van-button size="small"
                             :type="remarkItem.sweet=='正常糖'?'danger':''"
                             @click="handleSweet(remarkItem,'正常糖')"
                            >正常糖</van-button>
                            <van-button size="small"
                             :type="remarkItem.sweet=='七分糖'?'danger':''"
                             @click="handleSweet(remarkItem,'七分糖')"
                            >七分糖</van-button>
                            <van-button size="small"
                             :type="remarkItem.sweet=='五分糖'?'danger':''"
                             @click="handleSweet(remarkItem,'五分糖')"
                            >五分糖</van-button>
                            <van-button size="small"
                             :type="remarkItem.sweet=='三分糖'?'danger':''"
                             @click="handleSweet(remarkItem,'三分糖')"
                            >三分糖</van-button>
                            <van-button size="small"
                             :type="remarkItem.sweet=='无糖'?'danger':''"
                             @click="handleSweet(remarkItem,'无糖')"
                            >无糖</van-button>
                        </van-cell>
                    </div>

            <van-field
                type="textarea"
                v-model="remark"
                label="备注"
                placeholder="请输入备注"
                rows="2"
                autosize
                maxlength="500"
                clearable="true"
              >
            </van-dialog>


                <van-button type="primary" block @click.prevent="doOrder">下单</van-button>
            </van-list>

</van-row>

        </div>`,
        data() {
            return {
                activeKey: 0,
                images: [
                    `${serverUrl}file/download?fileName=奶茶轮播2.jpg`,
                    `${serverUrl}file/download?fileName=奶茶轮播3.jpg`,
                    `${serverUrl}file/download?fileName=奶茶轮播4.jpg`,
                    `${serverUrl}file/download?fileName=奶茶轮播5.jpg`,
                    `${serverUrl}file/download?fileName=奶茶轮播6.jpg`,
                ],
                loading: false,
                finished: false,
                list: [],
                show: false,
                orderItems: [],
                orderItemCount: 0,
                remark: '',
                remarkLast: '',
                remarkInput: '',
                remarkItems: [],
                remarkItem: {
                    temp: '正常冰',
                    sweet: '正常糖',
                },
            }
        },
        methods: {
            async onLoad() {
                console.log('onLoad')
                let res = await api.listItem()
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    this.list = res.data
                    this.list.forEach(e => e.stepper = 0)
                    this.updateOrderItems()
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
                store.state.componentState = this
            },
            async doOrder() {
                let orderItems = this.orderItems
                if (!orderItems.length) {
                    vant.Toast('您未选择任何商品')
                    return;
                }
                this.show = true
            },
            async doCreateOrder() {
                let remark = this.remark
                let orderItems = this.orderItems
                if (!orderItems.length) {
                    vant.Toast('您未选择任何商品')
                    return;
                }
                let orderData = {
                    remark,
                    items: orderItems,
                }
                let res = await api.createOrder(orderData)
                if (res.code == 0) {
                    this.orderItems = []
                    this.orderItemCount = 0
                    this.show = false
                    vant.Toast('创建订单成功!')
                    window.location.hash = '#/orderList'
                } else {
                    vant.Toast('创建订单失败!')
                }
            },
            doScroll(item) {
                let { id, type } = item
                console.log('定位到', id, type)
                let el = document.getElementById(id)
                // el.scrollIntoView()
                let oldColor = el.style.backgroundColor
                // el.style.backgroundColor = '#aaa'
                highlightAfterScroll(id, '#aaa', 200)
                // setTimeout(() => el.style.backgroundColor = oldColor, 150)
            },
            handleChange(item) {
                console.log('handleChange', item)
                this.updateOrderItems()
            },
            updateOrderItems() {
                let list = this.list.filter(e => e.stepper)
                let orderItemCount = 0
                let orderItems = list.map(e => {
                    orderItemCount += e.stepper
                    return {
                        itemId: e.id,
                        quantity: e.stepper,
                        imageUrl: e.imageUrl,
                        name: e.name,
                        temp: '正常冰',
                        sweet: '正常糖',
                    }
                })
                this.orderItems = orderItems
                this.orderItemCount = orderItemCount
                let remarkItems = []
                let active = true
                let ind = 0
                orderItems.forEach(item => {
                    let { itemId, name, quantity, imageUrl } = item
                    for (let i = 0; i < quantity; i++) {
                        let remarkItem = { ind: ind++, itemId, name, imageUrl, temp: '正常冰', sweet: '正常糖', active, clicked: active }
                        if (active) {
                            active = false
                            this.remarkItem = remarkItem
                        }
                        if (quantity > 1) {
                            remarkItem.name = name + '_' + (i + 1)
                        }
                        remarkItems.push(remarkItem)
                    }
                })
                this.remarkItems = remarkItems
                console.log('orderItems: %s, orderItemCount: %s, remarkItems: %s', orderItems, orderItemCount, remarkItems)
            },
            handleTemp(remarkItem, temp = '正常冰') {
                remarkItem.temp = temp
                this.remark = this.remarkItems.filter(e => e.clicked).map(e => `${e.name} ${e.temp} ${e.sweet}`).join('\n')
            },
            handleSweet(remarkItem, sweet = '正常糖') {
                remarkItem.sweet = sweet
                this.remark = this.remarkItems.filter(e => e.clicked).map(e => `${e.name} ${e.temp} ${e.sweet}`).join('\n')
            },
        },
    };

    const Item = {
        template: `
        <div>
            <van-list
            v-model="loading"
            :finished="finished"
            finished-text="没有更多了"
            error-text="请求失败，点击重新加载"
            @load="onLoad"
            >


            <!--使用title-style title-class label-class value-class 自定义样式，通过设置less-spacing减少标题和标题下方的描述信息的间距 -->
            <van-cell-group>
                <van-cell
                    v-for="(item, index) in list"
                    :key="index"
                    less-spacing
                    title-style="flex: 3"
                    title-class="van-multi-ellipsis--l2"
                    label-class="font-size0 van-color-text-secondary"
                    value-class="margin-left38 flex-align-spacebetween"
                >

                    <template slot="title">
                        <span class="van-multi-ellipsis--l2">{{ item.name }}</span>
                        <img style="width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+item.imageUrl" />

                    </template>
                    <template slot="label">{{ item.type }} </template>
                    <template>

                        <van-space direction="vertical" fill>
                            <div class="font-size1 van-color-text-assist">
                                库存 {{ item.quantity }}
                            </div>
                            <div class="font-size2 van-color-text-assist">
                                {{ item.price }}
                                <i class="font-size-2">元</i>
                            </div>
                            <div>
                                
                                <van-button type="primary" size="mini"  @click.prevent="doEdit(item)">修改</van-button>
                                <van-button type="danger" size="mini"  @click.prevent="doDelete(item)">删除</van-button>
                            </div>
                        </van-space>
                    </template>

                </van-cell>
            </van-cell-group>



            <van-button type="primary" block @click.prevent="doAdd">新增</van-button>
            </van-list>

            <van-popup
            v-model:show="show"
            position="bottom" closeable
            >
                <van-form @submit="onSubmit">
                    <van-cell-group inset :title="operate">
                        <van-field name="uploader" label="图片上传" style="padding-top:10px">
                            <template #input>
                            <van-uploader v-model="value" :deletable="false" :max-count="2" />
                            </template>
                        </van-field>
                        <van-field
                          v-model="item.name"
                          name="username"
                          label="名称"  
                          placeholder="请填写名称" autocomplete="off"
                          :rules="[{ required: true, message: '请填写名称' }]"
                        />
                        <van-field
                          v-model="item.price"
                          name="username"
                          label="价格" 
                          placeholder="请填写价格" autocomplete="off"
                          :rules="[{ required: true, message: '请填写价格' }]"
                        />
                        <van-field
                          v-model="item.type"
                          name="username"
                          label="类别" 
                          placeholder="请填写类别" autocomplete="off"
                          :rules="[{ required: true, message: '请填写类别' }]"
                        />
                        <van-field
                          v-model="item.quantity"
                          name="username"
                          label="数量" 
                          placeholder="请填写数量" autocomplete="off"
                          :rules="[{ required: true, message: '请填写数量' }]"
                        />
                    </van-cell-group>

                    <div style="margin: 16px;">
                        <!-- 设置垂直间距 -->
                        <van-row :gutter="20">
                        <van-col span="24">
                            <van-button round block type="primary" native-type="submit" @click.prevent="onSubmit(item)" >
                            提交
                            </van-button></van-col>
                        </van-row>
                    </div>
                </van-form>
            </van-popup>

        </div>`,
        data() {
            return {
                loading: false,
                finished: false,
                list: [],
                // 对话框
                show: false,
                operate: '修改',
                value: [
                    {
                        url: 'http://bs.1uu.pw:8005/file/download?fileName=草莓芝士奶茶.jpg'
                    },
                ],
                item: {
                    "id": "18fe3bf1142c35935b8722afb483d99d",
                    "name": "草莓芝士奶茶",
                    "price": 17,
                    "type": "草莓奶盖茶",
                    "imageUrl": "草莓芝士奶茶.jpg",
                    "quantity": 80,
                    "updateTime": "2025-05-11T02:46:22.000+0000",
                    "createTime": "2025-05-11T02:46:22.000+0000"
                },
            }
        },
        created() {
            store.state.componentState = this
        },
        methods: {
            async onLoad() {
                console.log('onLoad')
                let res = await api.listItem()
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    this.list = res.data
                    this.list.forEach(e => e.stepper = 0)
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
            },
            async doEdit(item) {
                this.operate = '修改'
                this.item = item
                this.value = [{ url: `${serverUrl}/file/download?fileName=${item.imageUrl}`, }]
                this.show = true
            },
            async doDelete(item) {
                let { id, name } = item
                vant.Dialog({
                    title: `是否删除 ${name}?`,
                    showConfirmButton: true, showCancelButton: true,
                }).then(async (opt) => {
                    // on comfirm
                    console.log('删除', id, opt)
                    let res = await api.deleteItem(id)
                    if (res.code == 0) {
                        console.log('删除成功', res.data)
                        vant.Toast(`已删除 ${name}`)
                        this.onLoad()
                    } else {
                        vant.Toast('删除失败, 请重试')
                    }
                }).catch(() => {
                    console.log('cancel')
                });
            },
            async doAdd() {
                this.operate = '新增'
                let addItem = {
                    "name": "",
                    "price": 0,
                    "type": "",
                    "imageUrl": "",
                    "quantity": 0,
                }
                this.item = addItem
                this.value = []
                this.show = true
            },
            async onSubmit() {
                let operate = this.operate
                console.log('-----提交-----', operate)
                let item = this.item
                let value = this.value
                if (value[0]) {
                    item.imageUrl = value[0].url.split('fileName=').pop()
                }
                if (!this.doCheck(item)) {
                    console.error('信息不正确', item)
                    setTimeout(() => {
                        // vant.Toast('信息不正确')
                    }, 1000)
                    return
                }
                if (operate == '修改') {
                    let res = await api.updateItem(item)
                    if (res.code == 0) {
                        console.log('修改成功', res.data)
                        vant.Toast(`成功修改`)
                        this.show = false
                        this.onLoad()
                    } else {
                        vant.Toast('修改失败, 请重试')
                    }
                }
                if (operate == '新增') {
                    let res = await api.addItem(item)
                    if (res.code == 0) {
                        console.log('新增成功', res.data)
                        vant.Toast(`成功新增`)
                        this.show = false
                        this.onLoad()
                    } else {
                        vant.Toast('新增失败, 请重试')
                    }
                }
            },
            doCheck(item) {
                let operate = this.operate
                let value = this.value
                let { id, name, price, type, imageUrl, quantity } = item
                if (!name) {
                    vant.Toast('名称不能为空')
                    return false
                }
                if (!price || price <= 0) {
                    vant.Toast('价格不正确')
                    return false
                }
                if (!type) {
                    vant.Toast('类型不能为空')
                    return false
                }
                if (!imageUrl) {
                    vant.Toast('图片未上传')
                    return false
                }
                if (!quantity || quantity <= 0) {
                    vant.Toast('数量不正确')
                    return false
                }
                if (operate == '新增' && !!id) {
                    vant.Toast('系统错误,多余id')
                    return false
                }
                if (operate == '修改' && !id) {
                    vant.Toast('系统错误,缺少id')
                    return false
                }
                if (!value || value.length == 0) {
                    vant.Toast('未上传图片')
                    return false
                }
                return true
            },
            async doUpload(imgData) {
                let { file } = imgData
                if (!file) {
                    console.log('未选择图片')
                    return
                }
                let fd = new FormData()
                fd.append('file', file)
                let res = await api.fileUpload(fd)
                if (res.code == 0) {
                    let imgUrl = res.data
                    let images = [{ url: `${serverUrl}${imgUrl}`, }]
                    console.log("成功上传了图片: ", images, imgUrl)
                    this.value = images
                }
            },
        },
        watch: {
            async value(newVal, oldVal) {
                console.log('选择图片', newVal, oldVal)
                let selectedFileImg = newVal.filter(e => e.file)[0]
                if (selectedFileImg) {
                    console.log('选择了新图片', selectedFileImg)
                    this.doUpload(selectedFileImg)
                }
            },
        },
    };

    const OrderList = {
        template: `
        <div>
            <van-tabs v-model="active">
                <van-tab title="今日订单" name="1" />
                <van-tab title="历史订单" name="2" />
            </van-tabs>
            <van-list
            v-model="loading"
            :finished="finished"
            finished-text="没有更多了"
            error-text="请求失败，点击重新加载"
            @load="onLoad"
            >


                <!--使用title-style title-class label-class value-class 自定义样式，通过设置less-spacing减少标题和标题下方的描述信息的间距 -->
                <van-cell-group>

                <div v-for="(item, index) in list">

                    <div v-if="new Date(item.createTime).getTime()>toDay.getTime()||active==2||!['CANCELED'].includes(item.status)">
                        <van-cell
                            :key="index"
                            less-spacing
                            title-style="flex: 5"
                            title-class="van-multi-ellipsis--l2"
                            label-class="font-size0 van-color-text-secondary"
                            value-class="margin-left38 flex-align-spacebetween"
                        >
                        <template>
                            </template>
                            <template slot="title">
                            <span class="van-multi-ellipsis--l2">{{ item.name }}</span>

                            <span v-for="(it, ind) in item.items">

                                <img v-for="n in it.quantity" :key="n" style="width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+it.imageUrl" />

                            </span>

                            </template>
                            <template slot="label">{{ item.type }}
                            
                                </template>
                            <template>
                            <span class="font-size1 van-color-text-assist">
                                {{ item.statusStr }}
                            </span>
                            <span class="font-size2 van-color-text-assist">
                            
                                总价<i class="font-size-2">{{ item.totalPrice }}</i> 元
                            <div v-if="item.status=='CREATED'">
                                <van-button type="primary" @click.prevent="doPay(item)" size="mini">付款</van-button>
                                <van-button type="danger" @click.prevent="doCancel(item)" size="mini">取消</van-button>
                            </div>
                            <div v-if="item.status=='FINISHED'">
                                <van-button disabled plain type="info" @click.prevent="doPay(item)" size="mini">已完成</van-button>
                            </div>
                            <div v-if="item.status=='CANCELED'">
                                <van-button disabled plain @click.prevent="doPay(item)" size="mini">已取消</van-button>
                            </div>
                            <div v-if="item.status=='WAITING'">
                                <van-button type="info" @click.prevent="doShowCode(item)" size="mini">取餐码</van-button>
                                <van-button plain type="info" @click.prevent="doShowCode(item)" size="mini">{{item.orderCode}}</van-button>
                            </div>
                            <div v-if="item.status=='PAID'">
                                <van-button type="warning" @click.prevent="doWaiting(item)" size="mini">备餐中</van-button>
                            </div>
                            </span>
                            </template>

                        </van-cell>
                    </div>
                
                </div>
                </van-cell-group>


            </van-list>


        </div>`,
        data() {
            return {
                active: 1,
                loading: false,
                finished: false,
                list: [],
                statusMap: {
                    CREATED: '等待付款',
                    PAID: '订单成功',
                    CANCELED: '订单取消',
                    WAITING: '订单就绪',
                    FINISHED: '订单完成',
                },
                toDay: new Date(),
                intervalId: 0,
            }
        },
        methods: {
            async onLoad() {
                let toDay = new Date()
                this.toDay = toDay
                toDay.setHours(0)
                toDay.setMinutes(0)
                toDay.setSeconds(0)
                toDay.setMilliseconds(0)
                console.log('onLoad')
                let res = await api.listOrder()
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    this.list = res.data
                    res.data.forEach(e => {
                        e.statusStr = this.statusMap[e.status]
                    })
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
            },
            async doCreateOrder() {
                let list = this.list.filter(e => e.stepper)
                if (!list.length) {
                    vant.Toast('错误: 未选择任何商品')
                    return;
                }
                let orderItems = list.map(e => {
                    return {
                        itemId: e.id,
                        quantity: e.stepper,
                    }
                })
                let res = await api.createOrder(orderItems)
                if (res.code == 0) {
                    vant.Toast('创建订单成功!')
                    window.location.hash = '#/orderList'
                } else {
                    vant.Toast('创建订单失败!')
                }
            },
            async doPay(item) {
                console.log('付款订单', item)
                let { id, totalPrice, items, status } = item
                if (status != 'CREATED') {
                    vant.Toast('订单状态无法付款')
                    return
                }
                let message = `是否购买 ${items.length} 件商品, 合计 ${totalPrice} 元`;
                vant.Dialog({
                    title: '是否购买',
                    showCancelButton: true,
                    closeOnClickOverlay: true,
                    closeOnPopstate: true,
                    message: message,
                    confirmButtonText: '立即支付',
                    cancelButtonText: '考虑考虑',
                }).then(async () => {
                    console.log('确认付款', id)
                    let res = await api.payOrder(id)
                    if (res.code == 0) {
                        vant.Toast(`成功支付${totalPrice}元`)
                        this.onLoad()
                    } else {
                        vant.Toast(`支付失败! ` + res.message)
                    }
                }).catch(() => {
                    console.log('取消')
                })
            },
            async doCancel(item) {
                console.log('取消订单', item)
                let { id, totalPrice, items, status } = item
                if (status != 'CREATED') {
                    vant.Toast('订单状态无法取消')
                    return
                }
                let message = `是否取消该订单?\n包含 ${items.length} 件商品, 合计 ${totalPrice} 元`;
                vant.Dialog({
                    title: '是否取消',
                    showCancelButton: true,
                    closeOnClickOverlay: true,
                    closeOnPopstate: true,
                    message: message,
                    confirmButtonText: '立即取消',
                    cancelButtonText: '考虑考虑',
                }).then(async () => {
                    console.log('确认取消', id)
                    let res = await api.cancelOrder(id)
                    if (res.code == 0) {
                        vant.Toast(`订单已取消`)
                        this.onLoad()
                    } else {
                        vant.Toast(`订单取消失败`)
                    }
                }).catch(() => {
                    console.log('取消')
                })
            },
            async doShowCode(item) {
                console.log('显示取餐码')
                let { id, orderCode } = item
                let intervalId = this.intervalId
                clearInterval(intervalId)

                intervalId = setInterval(async () => {
                    let res = await api.findOrder(id)
                    if (res.code == 0) {
                        console.log('订单查询成功', res.data)
                        let { status } = res.data
                        if (status == 'FINISHED') {
                            item.status = 'FINISHED'
                            vant.Dialog.close()
                            vant.Notify({ type: 'success', message: '已成功验码, 请取走你的餐品', duration: 5000 });
                            clearInterval(intervalId)
                        }
                    } else {
                        console.error('查询订单失败', id, res)
                        vant.Toast('查询订单失败, 请刷新重试')
                    }
                }, 2000)

                this.intervalId = intervalId
                vant.Dialog.alert({
                    title: `你的取餐码: ${orderCode}`,
                    message: `请将取餐码展示给工作人员`,
                }).then(() => {
                    clearInterval(intervalId)
                }).catch(() => {
                    clearInterval(intervalId)
                })
            },
            async doWaiting() {
                vant.Toast("正在备餐中,请稍等!")
            },
        },
        watch: {
            active(newVal, oldVal) {
                this.onLoad()
            }
        },
    };

    const OrderListManage = {
        template: `
        <div>
            <van-list
            v-model="loading"
            :finished="finished"
            finished-text="没有更多了"
            error-text="请求失败，点击重新加载"
            @load="onLoad"
            >


            <!--使用title-style title-class label-class value-class 自定义样式，通过设置less-spacing减少标题和标题下方的描述信息的间距 -->
            <van-cell-group>
            <van-cell
                v-for="(item, index) in list"
                :key="index"
                less-spacing
                title-style="flex: 5"
                title-class="van-multi-ellipsis--l2"
                label-class="font-size0 van-color-text-secondary"
                value-class="margin-left38 flex-align-spacebetween"
            >
            <template>
                </template>
                <template slot="title">
                <span class="van-multi-ellipsis--l2">{{ item.name }}</span>

                <span v-for="(it, ind) in item.items">

                    <img v-for="n in it.quantity" :key="n" style="width:50px;height:50px;" :src="serverUrl+'file/download?fileName='+it.imageUrl" />

                </span>
                
                </template>
                <template slot="label">{{ formatTime(item.createTime,'M月d日 HH:mm')}} {{ item.userName }} 的订单
                   
                    </template>
                <template>
                <span class="font-size1 van-color-text-assist">
                     {{ item.statusStr }}
                </span>
                <span class="font-size2 van-color-text-assist">
               
                    总价<i class="font-size-2">{{ item.totalPrice }}</i>元
                <div v-if="item.status=='PAID'">
                    <van-button type="info" @click.prevent="doWaiting(item)" size="mini">就绪</van-button>
                </div>
                <div v-if="item.status=='WAITING'">
                    <van-button type="primary" @click.prevent="doCodeOrder(item)" size="mini">验码</van-button>
                </div>
                <div v-if="item.status=='FINISHED'">
                    <van-button plain type="primary" disabled @click.prevent="" size="mini">已完成</van-button>
                </div>
                <div v-if="item.status=='CANCELED'">
                    <van-button plain disabled @click.prevent="" size="mini">已取消</van-button>
                </div>
                <div v-if="item.status=='CREATED'">
                    <van-button plain type="warning" disabled @click.prevent="" size="mini">待付款</van-button>
                    <!-- <van-button plain type="info" @click.prevent="doChangeOrder(item)" size="mini">改价</van-button> -->
                </div>
                </span>
                </template>
                
            </van-cell>
            </van-cell-group>


            <!-- 输入框 -->
            <van-dialog v-model="show" :title="'请输入用户 '+orderUserName+' 的取餐码'" show-cancel-button :lazy-render="false"
                @confirm="onConfirmCodeOrder(item)" 
                @cancel="clearCode"    
            >
                <van-field
                    type="input"
                    v-model="message"
                    rows="2"
                    autosize
                    autofocus
                    maxlength="8"
                    placeholder="请输入取餐码"
                    show-word-limit
                    class="message"
                />
            </van-dialog>


        </div>`,
        data() {
            return {
                show: false,
                message: '',
                loading: false,
                finished: false,
                list: [],
                statusMap: {
                    CREATED: '等待付款',
                    PAID: '订单成功',
                    CANCELED: '订单取消',
                    WAITING: '订单就绪',
                    FINISHED: '订单完成',
                },
                item: {},
                // 订单的用户名
                orderUserName: '',
            }
        },
        methods: {
            async onLoad() {
                console.log('onLoad')
                let res = await api.orderListManage()
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    this.list = res.data
                    res.data.forEach(e => {
                        e.statusStr = this.statusMap[e.status]
                    })
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
            },
            async doCreateOrder() {
                let list = this.list.filter(e => e.stepper)
                if (!list.length) {
                    vant.Toast('错误: 未选择任何商品')
                    return;
                }
                let orderItems = list.map(e => {
                    return {
                        itemId: e.id,
                        quantity: e.stepper,
                    }
                })
                let res = await api.createOrder(orderItems)
                if (res.code == 0) {
                    vant.Toast('创建订单成功!')
                    window.location.hash = '#/orderList'
                } else {
                    vant.Toast('创建订单失败!')
                }
            },
            async doWaiting(item) {
                console.log('已就绪订单', item)
                let { id, totalPrice, items, status, remark } = item
                if (status != 'PAID') {
                    vant.Toast('订单状态无法已就绪')
                    return
                }
                let remarkMsg = remark ? `\n\n订单备注: \n${remark}` : ''
                let message = `是否已就绪 ${items.length} 件商品, 合计 ${totalPrice} 元 ${remarkMsg}`;
                vant.Dialog({
                    title: '是否已就绪',
                    showCancelButton: true,
                    closeOnClickOverlay: true,
                    closeOnPopstate: true,
                    message: message,
                    confirmButtonText: '立即已就绪',
                    cancelButtonText: '还要一会',
                }).then(async () => {
                    console.log('确认已就绪', id)
                    let res = await api.waitingOrder(id)
                    if (res.code == 0) {
                        vant.Toast(`成功就绪 ${items.length} 杯奶茶`)
                        this.onLoad()
                    } else {
                        vant.Toast(`操作失败! ` + res.message)
                    }
                }).catch(() => {
                    console.log('取消')
                })
            },
            async doCodeOrder(item) {
                console.log('验码订单', item)
                let { id, totalPrice, items, status, userName } = item
                if (status != 'WAITING') {
                    vant.Toast('订单状态无法验码')
                    return
                }
                this.show = true
                this.item = item
                this.orderUserName = userName
            },
            async onConfirmCodeOrder() {
                let { id, totalPrice, items, status } = this.item
                let orderCode = this.message
                console.log('输入取餐码:', orderCode)
                if (!orderCode) {
                    vant.Toast('未输入取餐码')
                }
                let res = await api.codeOrder(id, orderCode)
                if (res.code == 0) {
                    vant.Toast('验码成功!')
                    this.onLoad()
                } else {
                    vant.Toast('验码失败!' + res.message)
                }
            },
            clearCode() {
                console.log('clearCode')
                this.value = ''
            },
        }
    };

    const PersonList = {
        template: `
        <div>
            <van-tabs v-model="active">
                <van-tab title="消费统计" name="1" />
                <van-tab :title="sharedState.admin?'交易明细':'消费明细'" name="2" />
                <van-tab title="个人信息" name="3" />
            </van-tabs>
            
            <van-cell-group v-if="active==1">
              
                <van-cell v-if="sharedState.admin"
                    less-spacing
                    title-style="flex: 5"
                    title-class="van-multi-ellipsis--l2"
                    label-class="font-size0 van-color-text-secondary"
                    value-class="margin-left38 flex-align-spacebetween"
                >
                    <template slot="title">
                    <span class="van-multi-ellipsis--l2">注册人数</span>
                    </template>
                    <template slot="label">{{  }}</template>
                    <template>
                    <span class="font-size1 van-color-text-assist">
                        {{  }}
                    </span>
                    <span class="font-size2 van-color-text-assist">
                        {{ totalUsers }}<i class="font-size-2">人</i>
                    </span>
                    </template>
                </van-cell>
                <van-cell
                    less-spacing
                    title-style="flex: 5"
                    title-class="van-multi-ellipsis--l2"
                    label-class="font-size0 van-color-text-secondary"
                    value-class="margin-left38 flex-align-spacebetween"
                >
                    <template slot="title">
                    <span class="van-multi-ellipsis--l2">{{sharedState.admin?'付费用户':'注册会员'}}</span>
                    </template>
                    <template slot="label">{{  }}</template>
                    <template>
                    <span class="font-size1 van-color-text-assist">
                        {{  }}
                    </span>
                    <span class="font-size2 van-color-text-assist">
                        {{ sharedState.admin?totalPayUsers:userCreated }}<i class="font-size-2">{{sharedState.admin?'人':'天'}}</i>
                    </span>
                    </template>
                </van-cell>
                <van-cell
                    less-spacing
                    title-style="flex: 5"
                    title-class="van-multi-ellipsis--l2"
                    label-class="font-size0 van-color-text-secondary"
                    value-class="margin-left38 flex-align-spacebetween"
                >
                    <template slot="title">
                    <span class="van-multi-ellipsis--l2">{{sharedState.admin?'累计收入':'累计消费'}}</span>
                    </template>
                    <template slot="label">{{  }}</template>
                    <template>
                    <span class="font-size1 van-color-text-assist">
                        {{  }}
                    </span>
                    <span class="font-size2 van-color-text-assist">
                        {{ totalCost }}<i class="font-size-2">元</i>
                    </span>
                    </template>
                </van-cell>
                <van-cell
                    less-spacing
                    title-style="flex: 5"
                    title-class="van-multi-ellipsis--l2"
                    label-class="font-size0 van-color-text-secondary"
                    value-class="margin-left38 flex-align-spacebetween"
                >
                    <template slot="title">
                    <span class="van-multi-ellipsis--l2">{{sharedState.admin?'累计销售量':'购买奶茶'}}</span>
                    </template>
                    <template slot="label">{{  }}</template>
                    <template>
                    <span class="font-size1 van-color-text-assist">
                        {{  }}
                    </span>
                    <span class="font-size2 van-color-text-assist">
                        {{ totalCups }}<i class="font-size-2">杯</i>
                    </span>
                    </template>
                </van-cell>
            </van-cell-group>

            <van-list
            v-if="active==2"
            v-model="loading"
            :finished="finished"
            finished-text="没有更多了"
            error-text="请求失败，点击重新加载"
            @load="onLoad"
            >

                <van-cell-group v-for="(item, index) in list">
                    <van-cell
                      v-if="payedStatus.includes(item.status)"
                      :key="index"
                      less-spacing
                      title-style="flex: 5"
                      title-class="van-multi-ellipsis--l2"
                      label-class="font-size0 van-color-text-secondary"
                      value-class="margin-left38 flex-align-spacebetween"
                    >
                      <template slot="title">
                        <span class="van-multi-ellipsis--l2">{{sharedState.admin?item.userName+' ':''}}购买 {{item.items.map(e=>e.name)[0]}} 等 {{ item.items.length }} 件商品</span>
                      </template>
                      <template slot="label">{{ formatTime(item.createTime,'M月d日 HH:mm') }}</template>
                      <template>
                        <span class="font-size1 van-color-text-assist">
                          {{ item.unit }}
                        </span>
                        <span class="font-size2 van-color-text-assist">
                          消费{{ item.totalPrice }}<i class="font-size-2">元</i>
                        </span>
                      </template>
                    </van-cell>
                </van-cell-group>
            </van-list>


            <van-cell-group v-if="active==3">
              
              <van-field v-model="sharedState.info.name" label="用户名" readonly />
              <van-field v-model="sharedState.info.nickName" label="昵称" readonly />
              <van-field v-model="sharedState.info.tel" label="手机" readonly />
              <van-field v-model="sharedState.info.qq" label="QQ" readonly />
              <van-field v-model="sharedState.info.email" label="邮箱" readonly />
              <van-field v-model="sharedState.info.address" label="联系地址" readonly />
              <van-cell>
                <van-button type="primary" block @click.prevent="handleEdit('user')">修改信息</van-button>
              </van-cell>
              <van-cell>
                <van-button type="primary" block @click.prevent="handleEdit('pass')">修改密码</van-button>
              </van-cell>

              
            <van-dialog v-if="active==3" v-model="show" :confirm-button-text="'提交'" title="修改信息" show-cancel-button
            @confirm="doEdit"
            :before-close="beforeClose"
            >
                <van-cell-group v-if="type=='user'">
                    
                    <van-field v-model="edit.nickName" label="昵称"  />
                    <van-field v-model="edit.tel" label="手机"  />
                    <van-field v-model="edit.qq" label="QQ"  />
                    <van-field v-model="edit.email" label="邮箱"  />
                    <van-field v-model="edit.address" label="联系地址"  />

                </van-cell-group>
                <van-cell-group v-if="type=='pass'">
                    
                    <van-field v-model="edit.oldPass" label="旧密码" type="password" />
                    <van-field v-model="edit.newPass" label="新密码" type="password" />

                </van-cell-group>
            
            </van-dialog>
           
          </van-cell-group>


        </div>`,
        data() {
            return {
                active: 3,
                loading: false,
                finished: false,
                list: [],
                statusMap: {
                    CREATED: '等待付款',
                    PAID: '订单成功',
                    CANCELED: '订单取消',
                    WAITING: '订单就绪',
                    FINISHED: '订单完成',
                },
                payedStatus: ['PAID', 'WAITING', 'FINISHED',],
                toDay: new Date(),
                intervalId: 0,
                // 统计
                totalCost: 0,
                totalItems: 0,
                totalCups: 0,
                userCreated: 0,
                totalPayUsers: 0,
                totalUsers: 1,
                users: [],
                // 用户信息
                show: false,
                edit: {},
                type: 'user',
                editType: { user: 'user', pass: 'pass' },
                // 共享状态
                sharedState: store.state,
            }
        },
        created() {
            console.log('生命周期 created PersonList')
            let createTime = new Date(store.state.info.createTime)
            let oneDayMs = 1000 * 60 * 60 * 24
            let pastMs = Date.now() - createTime.getTime()
            let pastDay = Math.round(pastMs / oneDayMs)
            this.userCreated = pastDay
            console.log('用户注册已过时间 pastDay', pastDay)
            this.onLoad()
        },
        methods: {
            async onLoad() {
                let toDay = new Date()
                this.toDay = toDay
                toDay.setHours(0)
                toDay.setMinutes(0)
                toDay.setSeconds(0)
                toDay.setMilliseconds(0)
                console.log('onLoad')

                let res
                if (this.sharedState.admin) {
                    res = await api.orderListManage()
                    let resUser = await api.listUser()
                    if (res.code == 0) {
                        console.log('用户加载成功', res.data)
                        this.users = res.data
                        this.totalUsers = res.data.length
                    }
                } else {
                    res = await api.listOrder()
                }
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    this.list = res.data
                    res.data.forEach(e => {
                        e.statusStr = this.statusMap[e.status]
                    })
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
                store.state.componentState = this
            },
            async doCreateOrder() {
                let list = this.list.filter(e => e.stepper)
                if (!list.length) {
                    vant.Toast('错误: 未选择任何商品')
                    return;
                }
                let orderItems = list.map(e => {
                    return {
                        itemId: e.id,
                        quantity: e.stepper,
                    }
                })
                let res = await api.createOrder(orderItems)
                if (res.code == 0) {
                    vant.Toast('创建订单成功!')
                    window.location.hash = '#/orderList'
                } else {
                    vant.Toast('创建订单失败!')
                }
            },
            async doPay(item) {
                console.log('付款订单', item)
                let { id, totalPrice, items, status } = item
                if (status != 'CREATED') {
                    vant.Toast('订单状态无法付款')
                    return
                }
                let message = `是否购买 ${items.length} 件商品, 合计 ${totalPrice} 元`;
                vant.Dialog({
                    title: '是否购买',
                    showCancelButton: true,
                    closeOnClickOverlay: true,
                    closeOnPopstate: true,
                    message: message,
                    confirmButtonText: '立即支付',
                    cancelButtonText: '考虑考虑',
                }).then(async () => {
                    console.log('确认付款', id)
                    let res = await api.payOrder(id)
                    if (res.code == 0) {
                        vant.Toast(`成功支付${totalPrice}元`)
                        this.onLoad()
                    } else {
                        vant.Toast(`支付失败! ` + res.message)
                    }
                }).catch(() => {
                    console.log('取消')
                })
            },
            async doCancel(item) {
                console.log('取消订单', item)
                let { id, totalPrice, items, status } = item
                if (status != 'CREATED') {
                    vant.Toast('订单状态无法取消')
                    return
                }
                let message = `是否取消该订单?\n包含 ${items.length} 件商品, 合计 ${totalPrice} 元`;
                vant.Dialog({
                    title: '是否取消',
                    showCancelButton: true,
                    closeOnClickOverlay: true,
                    closeOnPopstate: true,
                    message: message,
                    confirmButtonText: '立即取消',
                    cancelButtonText: '考虑考虑',
                }).then(async () => {
                    console.log('确认取消', id)
                    let res = await api.cancelOrder(id)
                    if (res.code == 0) {
                        vant.Toast(`订单已取消`)
                        this.onLoad()
                    } else {
                        vant.Toast(`订单取消失败`)
                    }
                }).catch(() => {
                    console.log('取消')
                })
            },
            async doShowCode(item) {
                console.log('显示取餐码')
                let { id, orderCode } = item
                let intervalId = this.intervalId
                clearInterval(intervalId)

                intervalId = setInterval(async () => {
                    let res = await api.findOrder(id)
                    if (res.code == 0) {
                        console.log('订单查询成功', res.data)
                        let { status } = res.data
                        if (status == 'FINISHED') {
                            item.status = 'FINISHED'
                            vant.Notify({ type: 'success', message: '已成功验码, 请取走你的餐品', duration: 5000 });
                            clearInterval(intervalId)
                        }
                    } else {
                        console.error('查询订单失败', id, res)
                        vant.Toast('查询订单失败, 请刷新重试')
                    }
                }, 2000)

                this.intervalId = intervalId
                vant.Dialog.alert({
                    title: `你的取餐码: ${orderCode}`,
                    message: `请将取餐码展示给工作人员`,
                }).then(() => {
                    clearInterval(intervalId)
                }).catch(() => {
                    clearInterval(intervalId)
                })
            },
            handleEdit(type = 'user') {
                console.log('handleEdit', type)
                this.type = type
                if (type == this.editType.user) {
                    let { id, nickName, tel, qq, email, address } = this.sharedState.info
                    let edit = { id, nickName, tel, qq, email, address }
                    this.edit = edit
                } else {
                    let editPass = {
                        oldPass: '',
                        newPass: '',
                    }
                    this.edit = editPass
                }
                this.show = true
            },
            beforeClose(action, done) {
                console.log('beforeClose', action, done)
                if (action == 'confirm') {
                    done(false)
                }
                done()
            },
            async doEdit() {
                let type = this.type
                let edit = this.edit
                console.log('doEdit', type, edit)
                if (this.editType.user == type) {
                    let { id, nickName, tel, qq, email, address } = edit
                    if (!id) {
                        vant.Toast('用户id不存在')
                        return
                    }
                    let res = await api.updateUser(edit)
                    if (res.code == 0) {
                        console.log('修改用户信息成功', edit)
                        this.show = false
                        vant.Dialog.close()
                        vant.Toast('修改用户信息成功')
                    } else {
                        console.log('修改用户信息失败', res)
                        vant.Toast('修改用户信息失败')
                    }

                } else {

                    let { oldPass, newPass } = edit
                    if (!oldPass || !newPass) {
                        vant.Toast('密码不能为空')
                        return
                    }
                    if (oldPass == newPass) {
                        vant.Toast('密码不能相同')
                        return
                    }
                    let res = await api.updatePass(edit)
                    if (res.code == 0) {
                        console.log('修改密码成功', edit)
                        this.show = false
                        vant.Dialog.close()
                        vant.Toast('修改密码成功')
                    } else {
                        console.log('修改密码失败', res)
                        vant.Toast('修改密码失败')
                    }
                }
            },
            async doEditPass() {

            },
        },
        watch: {
            list(newVal, oldVal) {
                let totalCost = this.list.filter(e => this.payedStatus.includes(e.status)).reduce((res, el) => res += el.totalPrice, 0)
                this.totalCost = totalCost

                let totalItems = this.list.filter(e => this.payedStatus.includes(e.status)).reduce((res, el) => res += el.items.length, 0)
                this.totalItems = totalItems
                let totalCups = this.list.filter(e => this.payedStatus.includes(e.status)).reduce((res, el) => { el.items.forEach(f => res += (f.quantity || 1)); return res; }, 0)
                this.totalCups = totalCups
                let totalPayUsers = new Set(this.list.map(e => e.userId)).size
                this.totalPayUsers = totalPayUsers

            },
        }
    };

    const Login = {
        template: `
        <div>
            <van-cell-group>
                <van-field v-model="username" label="用户名" placeholder="请输入用户名" />
                <van-field v-if="!hidePass" v-model="password" type="password" label="密码" placeholder="请输入密码" />
                <van-field v-if="hidePass" v-model="password" label="密码" placeholder="请输入密码" />
                <van-button type="primary" block @click.prevent="lazyLogin">登录</van-button>
                <van-button block @click.prevent="doRegister">注册</van-button>
            </van-cell-group>
        </div>
        `,
        data() {
            return {
                username: '',
                password: '',
                hidePass: true,
            }
        },
        methods: {
            async lazyLogin() {
                this.hidePass = true
                let { username, password } = this
                this.username = ''
                this.password = ''
                setTimeout(() => this.doLogin(username, password), 1)
            },
            async doLogin(username, password) {
                console.log('Login 执行登录')
                setTimeout(() => this.hidePass = false, 1000)
                console.log(' username: %s, password: %s', username, password)
                let param = {
                    "username": username,
                    "password": password,
                }
                let res = await api.login(param)
                let { code, message } = res
                console.log('----res ---', res, message)
                if (res.code == 0 && res.data.token) {
                    console.log('登录成功, 欢迎光临', res.data.token)
                    vant.Toast('登录成功, 欢迎光临')
                    let token = JSON.stringify(res.data)
                    localStorage['token'] = token
                    globalThis.token = res.data.token
                    store.state.token = res.data.token
                    store.state.user = res.data.user.name
                    store.state.info = res.data.user
                    store.state.admin = !!res.data.user.admin || res.data.user.name == 'admin'
                    // 全是admin(调试使用)
                    // store.state.admin = true
                    if (store.state.admin) {
                        // 管理员首页
                        window.location.hash = '#/orderListManage'
                    } else {
                        window.location.hash = '#/home'
                    }
                } else {
                    vant.Toast('登录失败!\n' + res.message)
                }
            },
            async doRegister() {
                console.log('Login 执行注册')
                window.location.hash = '#/reg'
            }
        },
        mounted() {
            console.log('生命周期 mounted Login')
            setTimeout(() => this.hidePass = false, 1000)
        }
    };
    const Reg = {
        template: `
        <div>
            <van-cell-group>
                <van-field v-model="username" label="用户名" placeholder="请输入用户名" />
                <van-field v-model="password" label="密码" placeholder="请输入密码" />
                <van-button type="primary" block @click.prevent="doRegister">注册</van-button>
                <van-button block @click.prevent="doLogin">登录</van-button>
            </van-cell-group>
        </div>
        `,
        data() {
            return {
                username: '',
                password: '',
            }
        },
        methods: {
            async doLogin() {
                console.log('Reg 执行登录')
                window.location.hash = '#/login'
            },
            async doRegister() {
                console.log('Reg 执行注册')
                let { username, password } = this
                console.log(' username: %s, password: %s', username, password)
                let param = {
                    "name": username,
                    "password": password,
                }
                let res = await api.reg(param)
                if (res.code == 0) {
                    vant.Toast('注册成功, 请登录')
                    window.location.hash = '#/login'
                } else {
                    vant.Toast('注册失败!\n' + res.message)
                }
            }
        },
        mounted() {
            console.log('生命周期 mounted Login')
        }
    };

    const About = {
        template: `<div><h2>关于我们</h2><p>这是关于页面</p></div>`
    };

    const Contact = {
        template: `
        <div>
            <van-tabs v-model="active">
                <van-tab title="用户留言" name="1" />
                <van-tab title="联系我们" name="2" />
            </van-tabs>
            <div v-if="active==1" style="padding-bottom:48px;opacity: 0.9; background-color: rgb(255, 255, 255);">
            <van-list
              v-model="loading"
              :finished="finished"
              @load="onLoad"
            >
              <van-cell
                v-for="(item, index) in list"
                :key="item"
                :title="item"
              >
              <template  slot="title">
                [{{item.typeMsg}}] {{item.content}}
              </template>
              <template  slot="label">
                {{formatTime(item.createTime,"MM-dd HH:mm")}} {{item.userName}}
              </template>
              <van-rate v-model="item.rate" readonly />
              <van-button v-if="sharedState.admin" type="danger"  @click.prevent="doDelete(item)" size="mini">删除</van-button>
              </van-cell>
            </van-list>
            
            <van-pagination  style="    background-color: #fff;"
              v-model="pageNumber" 
              :total-items="totalCount" 
              :show-page-size="5" 
              :page-count="totalPage"
              :mode="'multi'"
              force-ellipses
            />
            
            <van-button v-if="!sharedState.admin" type="info" block @click.prevent="()=>show=!show">我要留言</van-button>
            </div>
            
            <van-dialog v-model="show" :confirm-button-text="'提交'" show-cancel-button
             @confirm="handleConfirm"
              @cancel="handleCancel"
              :before-close="beforeClose"
            >
                <div>
                <center ><h2>留言</h2></center>
            <van-cell-group>
                <van-cell>
                    <template  slot="title">
                        评分
                    </template>
                    <van-rate  slot="default" v-model="value" />
                </van-cell>
              <van-field
                type="textarea"
                v-model="message"
                label="留言"
                placeholder="请输入留言"
                rows="2"
                autosize
                maxlength="50"
                show-word-limit
              >
              </van-field>
                <van-cell>
                    <template  slot="title">
                        类型
                    </template>
                    <van-radio-group  slot="default"  v-model="radio">
                        <van-row>
                    <van-col span="12">
                    <van-radio name="MSG">留言</van-radio></van-col>
                    <van-col span="12">
                    <van-radio name="REPORT">投诉</van-radio></van-col>
                    </van-row>
                    </van-radio-group>
                </van-cell>
            </van-cell-group>
                </div>
            
            </van-dialog>
           
            <div v-if="active==2" style="opacity: 0.9;  background-color: rgb(255, 255, 255);">
                <van-cell-group>
                    <van-cell title="联系方式" value="13709061665" icon="contact"  />
                    <van-cell title="联系人" value="陈晓琪" icon="contact"  />
                    <van-cell title="联系地址" value="四川省成都市金牛区图书馆 -1F 10086号" icon="location-o" />
                </van-cell-group>
            </div>
        </div>`,
        data() {
            return {
                active: 1,
                value: 5,
                show: false,
                list: [],
                loading: false,
                finished: true,
                pageNumber: 1,
                pageSize: 8,
                totalPage: 0,
                totalCount: 0,
                message: '',
                radio: 'MSG',
                typeMapping: {
                    'MSG': '留言',
                    'REPORT': '投诉',
                },
                // 共享状态
                sharedState: store.state,
            }
        },
        created() {
            this.onLoad()
        },
        methods: {
            async onLoad() {
                console.log('onLoad')
                let param = {
                    pageSize: this.pageSize,
                    pageNumber: this.pageNumber,
                }
                let res = await api.pageMsg(param)
                if (res.code == 0) {
                    console.log('列表加载成功', res.data)
                    let { pageNumber, pageSize, records, totalCount, totalPage } = res.data
                    records.forEach(e => e.typeMsg = this.typeMapping[e.type])
                    this.list = records
                    this.pageNumber = pageNumber
                    this.pageSize = pageSize
                    this.totalPage = totalPage
                    this.totalCount = totalCount
                    this.list.forEach(e => e.stepper = 0)
                    this.finished = true
                } else {
                    vant.Toast('列表加载失败, 请刷新重试')
                }
                store.state.componentState = this
            },
            beforeClose(action, done) {
                console.log('beforeClose', action, done)
                let content = this.message
                if (action == 'confirm' && !content) {
                    done(false)
                }
                done()
            },
            async handleConfirm() {
                let content = this.message
                let rate = this.value
                let userId = store.state.info.id
                let type = this.radio
                if (!content) {
                    vant.Toast('请填写消息内容')
                    return
                }
                console.log('content: %s, rate: %s, userId: %s, type: %s', content, rate, userId, type)
                let msgData = {
                    userId, content, type, rate
                }
                let res = await api.addMsg(msgData)
                if (res.code == 0) {
                    console.log('留言成功', res)
                    vant.Toast('留言成功')
                    this.message = ''
                    this.value = 5
                    this.onLoad()
                } else {
                    console.log('留言失败')
                    vant.Toast('留言失败, 请刷新重试')
                }
            },
            async handleCancel() {
            },
            async doDelete(item) {
                let { id, userName } = item
                vant.Dialog({
                    title: `是否删除 ${userName} 的留言?`,
                    showConfirmButton: true, showCancelButton: true,
                }).then(async (opt) => {
                    // on comfirm
                    console.log('删除', id, opt)
                    let res = await api.deleteMsg(id)
                    if (res.code == 0) {
                        console.log('删除成功', res.data)
                        vant.Toast(`已删除 ${name}`)
                        this.onLoad()
                    } else {
                        vant.Toast('删除失败, 请重试')
                    }
                }).catch(() => {
                    console.log('cancel')
                });
            },
        },
        watch: {
            async pageNumber(newVal, oldVal) {
                console.log('pageNumber changed from %s to %s', oldVal, newVal)
                this.onLoad()
            }
        }
    };

    const NotFound = {
        template: `<div><h2>404 页面未找到</h2></div>`
    };


    // <!--  -->
    // <!-- 主代码 7/8 定义vue的路由配置 -->
    // <!--  -->
    // 路由配置
    const routes = {
        '/login': Login,
        '/reg': Reg,
        '/home': Home,
        '/orderList': OrderList,
        '/orderListManage': OrderListManage,
        '/personList': PersonList,
        '/about': About,
        '/contact': Contact,
        '/item': Item,
    };


    // <!--  -->
    // <!-- 主代码 8/8 定义vue的前端主程序框架。 -->
    // <!--  -->
    // 创建 Vue 实例
    new Vue({
        el: '#app',
        data: {
            // 共享状态
            sharedState: store.state,
        },
        mounted() {
            console.log('生命周期 mounted')
            document.body.style.backgroundImage = `url(${serverUrl}/file/download?fileName=背景.jpg)`
        },
        computed: {
            currentComponent() {
                console.log('生命周期 currentComponent')
                console.log('--currentComponent-', routes)
                console.log('当前路由', this.sharedState.currentRoute)
                this.sharedState.activeName = this.sharedState.currentRoute.split('/').pop()
                return routes[this.sharedState.currentRoute] || NotFound
            },
            myToken() {
                return this.sharedState.token
            },
            activeName() {
                return this.sharedState.activeName
            },
        },
        methods: {
            navigateTo(route) {
                window.location.hash = route
            },
            onClickLeft() {
                console.log('click left;')
            },
            async onClickRight() {
                console.log('click right;')
                delete localStorage['token']
                if (token) {
                    // 退出
                    let res = await api.logout()
                    token = ''
                    this.sharedState.token = ''
                    this.sharedState.user = ''
                    this.sharedState.info = {}
                    this.sharedState.admin = false
                }
                // 登录
                window.location.hash = '#/login'
            },
        },
        created() {
            console.log('生命周期 created')
            // 监听 hashchange 事件
            window.addEventListener('hashchange', () => {
                this.sharedState.currentRoute = window.location.hash.slice(1)
                console.log('this.currentRoute', this.sharedState.currentRoute)
            });

            // 初始化时处理 hash
            if (!window.location.hash) {
                window.location.hash = '#/home'
            }

            let loginData = localStorage['token'] && JSON.parse(localStorage['token'])
            if (loginData) {
                this.sharedState.token = loginData.token
                this.sharedState.user = loginData.user.name
                this.sharedState.info = loginData.user
                this.sharedState.admin = !!loginData.user.admin || loginData.user.name == 'admin'
                // 全是admin(调试使用)
                // this.sharedState.admin = true
                globalThis.token = this.sharedState.token
                console.log('已登录,token: ', this.sharedState.token)
            }
            // 验证登录token
            if (!this.sharedState.token) {
                // 没有登录
                vant.Toast('请先登录')
                window.location.hash = '#/login'
            }
        },
        watch: {
            activeName(newVal, oldVal) {
                console.log('activeName changed from %s to %s', oldVal, newVal, this.sharedState.currentRoute)

                // 验证登录token
                if (!this.sharedState.token) {
                    // 没有登录
                    let noTokenVisit = ['reg', 'login']
                    if (!noTokenVisit.includes(this.sharedState.activeName)) {
                        vant.Toast('请先登录')
                        window.location.hash = '#/login'
                        return
                    }
                }
                window.location.hash = '#/' + newVal
            },
            myToken(newVal, oldVal) {
                console.log('myToken changed from %s to %s', oldVal, newVal, this.sharedState.currentRoute)
            },
        }
    });
    // 调用函数组件，弹出一个 Toast
    // vant.Toast('欢迎光临');

</script>
<script src="index.js"></script>

</html>